package modelarts

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	modelArtsCore "modelArts/core"
	"net/http"
	"strings"
	"time"
	// "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/as/v1/region"
)

type HWcloudBody struct {
	Token HWcloudToken `json:"token"`
}

type HWcloudToken struct {
	ExpiresAt string                `json:"expires_at"`
	IssuedAt  string                `json:"issued_at"`
	Catalog   []HWcloudTokenCatalog `json:"catalog"`
	Domain    HWcloudTokenDomain    `json:"domain"`
	Methods   []string              `json:"methods"`
	Project   HWcloudTokenProject   `json:"project"`
	Roles     []HWcloudTokenRole    `json:"roles"`
	User      HWcloudTokenUser      `json:"user"`
}
type HWcloudTokenCatalog struct {
	Endpoints []HWcloudTokenCatalogEndpoints `json:"endpoints"`
	ID        string                         `json:"id"`
	Name      string                         `json:"name"`
	Type      string                         `json:"type"`
}

type HWcloudTokenCatalogEndpoints struct {
	ID        string `json:"id"`
	Interface string `json:"interface"`
	Region    string `json:"region"`
	RegionID  string `json:"region_id"`
	Url       string `json:"url"`
}
type HWcloudTokenProject struct {
	ID     string             `json:"id"`
	Name   string             `json:"name"`
	Domain HWcloudTokenDomain `json:"domain"`
}
type HWcloudTokenDomain struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}
type HWcloudTokenRole struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}
type HWcloudTokenUser struct {
	ID                string             `json:"id"`
	Name              string             `json:"name"`
	PasswordExpiresAt string             `json:"password_expires_at"`
	Domain            HWcloudTokenDomain `json:"domain"`
}

// 获取token
func GetToken(ak, sk, iamName, iamPswd, acountID, accountName, projectid, region string) (token *HWcloudToken, tokenValue string, err error) {
	if len(ak) == 0 {
		err = fmt.Errorf("access token not allowed empty")
		return
	}
	if len(sk) == 0 {
		err = fmt.Errorf("secret token not allowed empty")
		return
	}
	if len(iamName) == 0 {
		err = fmt.Errorf("iamName not allowed empty")
		return
	}
	if len(iamPswd) == 0 {
		err = fmt.Errorf("iamPswd not allowed empty")
		return
	}
	if len(acountID) == 0 {
		err = fmt.Errorf("acountID not allowed empty")
		return
	}
	if len(accountName) == 0 {
		err = fmt.Errorf("accountName not allowed empty")
		return
	}
	if len(projectid) == 0 {
		err = fmt.Errorf("projectid not allowed empty")
		return
	}
	if len(region) == 0 {
		err = fmt.Errorf("region not allowed empty")
		return
	}

	s := modelArtsCore.Signer{
		Key:    ak,
		Secret: sk,
	}
	data := fmt.Sprintf(`{
		"auth": {
		 "identity": {
		  "methods": [
		   "password" 
		  ],
		  "password": {
		   "user": {
			"domain": {
			 "name": "%s"
			},
			"name": "%s",
			"password": "%s"
		   }
		  }
		 },
		 "scope": {
		  "domain": {
		   "id": "%s",
		   "name": "%s"
		  },
		  "project": {
			"id": "%s",
			"name": "%s"
		   }
		 }
		}
	   }`, accountName, iamName, iamPswd, acountID, accountName, projectid, region)
	r, _ := http.NewRequest("POST", "https://iam."+region+".myhuaweicloud.com/v3/auth/tokens", ioutil.NopCloser(bytes.NewBufferString(data)))
	r.Header.Add("content-type", "application/json")
	err = s.Sign(r)
	if err != nil {
		return
	}
	client := http.DefaultClient
	resp, err := client.Do(r)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	respBodyBytes, _ := ioutil.ReadAll(resp.Body)
	if len(resp.Header.Get("X-Subject-Token")) == 0 {
		err = fmt.Errorf("GetToken Error:%s", string(respBodyBytes))
		return
	}
	var hwToken HWcloudBody
	err = json.Unmarshal(respBodyBytes, &hwToken)
	if err != nil {
		return
	}
	return &hwToken.Token, resp.Header.Get("X-Subject-Token"), nil
}
func convertTime(inputTime int) string {
	return time.Unix(int64(inputTime/1000), 0).In(ZhTime).Format("2006-01-02 15:04:05")
}

func convertRuntime(inputTime int) string {
	inputTime = inputTime / 1000 //毫秒转为秒
	day := inputTime / 3600 * 24
	dayStr := ""
	if day > 0 {
		dayStr = fmt.Sprintf("%d day, ", day)
	}
	hour := inputTime / 3600
	hourStr := ""
	if hour < 10 {
		hourStr = fmt.Sprintf("0%d", hour)
	} else {
		hourStr = fmt.Sprintf("%d", hour)
	}
	min := inputTime / 60
	minStr := ""
	if min < 10 {
		minStr = fmt.Sprintf("0%d", min)
	} else {
		minStr = fmt.Sprintf("%d", min)
	}
	sec := inputTime % 60
	secStr := ""
	if sec < 10 {
		secStr = fmt.Sprintf("0%d", sec)
	} else {
		secStr = fmt.Sprintf("%d", sec)
	}
	return fmt.Sprintf("%s%s:%s:%s", dayStr, hourStr, minStr, secStr)
}
func easyStatus(phase string) string {
	// ModelArts phase: "Creating"、"Pending"、"Running"、"Failed"、"Completed"、"Terminating"、"Terminated"、"Abnormal"
	// 简化status phase转为只有四个状态即
	// 	 Running：训练正常运行的状态，运行中
	// 	 Failed：训练出现错误的状态，运行失败
	// 	 Terminated：终止后的状态，已终止
	// 	 Completed：运行完成的状态，已完成
	switch phase {
	case "Creating":
		fallthrough
	case "Pending":
		fallthrough
	case "Running":
		return "Running"
	case "Terminating":
		fallthrough
	case "Terminated":
		return "Terminated"
	case "Failed":
		fallthrough
	case "Abnormal":
		return "Failed"
	default:
		return phase
	}

}

// 判断是Ascend 还是GPU
func getTrainInstanceTypesByVersion(engineVersion, flavor_id string) string {
	lowerVersion := strings.ToLower(engineVersion)
	var result []AscendVersion
	if strings.Contains(lowerVersion, "cann") {
		result = VersionAscendList
	} else if strings.Contains(lowerVersion, "cuda") {
		result = VersionNVIDIAList
	}
	for _, version := range result {
		if version.ID == flavor_id {
			return version.Name
		}
	}
	return "unknown"
}

// 用羲和前端认可的格式 编码job列表
func formatJobList(joblist *JobList) (list []*DisplayJob) {
	for _, jobitem := range joblist.Items {
		list = append(list, jobitem.Format())
	}
	return
}

func CheckToken(region, token string) error {
	r, _ := http.NewRequest("GET", "https://iam."+region+".myhuaweicloud.com/v3/auth/tokens", nil)
	r.Header.Add("content-type", "application/json;charset=UTF-8")
	r.Header.Add("X-Subject-Token", token)
	r.Header.Add("X-Auth-Token", token)
	resp, err := http.DefaultClient.Do(r)
	if err != nil {
		return err
	}

	defer resp.Body.Close()
	respBodyBytes, _ := ioutil.ReadAll(resp.Body)
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("CheckToken Error:%s", string(respBodyBytes))
	}

	var hwToken HWcloudBody
	err = json.Unmarshal(respBodyBytes, &hwToken)
	if err != nil {
		return err
	}
	expireTime, err := time.Parse(time.RFC3339Nano, hwToken.Token.ExpiresAt)
	if err != nil {
		return err
	}
	if expireTime.Before(time.Now()) {
		return fmt.Errorf("已经于%s 过期", expireTime.String())
	}
	// log.Println(expireTime.In(timeloca).String())

	return nil
}

//   CheckError 检查状态码是否符合预期，如果不符合，那么将错误信息封装输出。
func CheckError(expectCode, realCode int, errorStr string) (errorMsg *JobErrorMsg, err error) {
	if expectCode != realCode {
		errorMsg = new(JobErrorMsg)
		err = json.Unmarshal([]byte(errorStr), errorMsg)
		if err != nil {
			return nil, err
		}
	}
	return
}
